package com.gitee.wsl.android.ui.sample.icon.load


import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.SurfaceView
import android.view.SurfaceHolder


/**
 * Created by codeest on 2016/11/15.
 *
 * 我还在好奇里面装的究竟是啤酒还是橙汁 0v0
 */
class ENLoadingView : SurfaceView {
    private lateinit var mPaint: Array<Paint?>
    private lateinit var mBeerPaint: Array<Paint?>
    private lateinit var mBubblePaint: Array<Paint?>
    private var mPath: Path? = null
    private var mBgPath: Path? = null
    private var mThread: Thread? = null
    private lateinit var isItemReady: BooleanArray
    private lateinit var mCurrentRippleX: FloatArray
    private lateinit var mFraction: FloatArray
    private var mTemp = 0f
    private var mCurrentState = 0
    private var mWidth = 0f
    private var mHeight = 0f
    private var mCenterX = 0f
    private var mCenterY = 0f
    private var surfaceHolder: SurfaceHolder? = null
    private var mBaseLength = 0f
    private var mBgBaseLength = 0f

    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    private fun init() {
        mPaint = arrayOfNulls(4)
        mBeerPaint = arrayOfNulls(4)
        mBubblePaint = arrayOfNulls(4)
        mPath = Path()
        mBgPath = Path()
        isItemReady = BooleanArray(4)
        mFraction = FloatArray(4)
        mCurrentRippleX = FloatArray(4)
        mCurrentState = STATE_HIDE
        for (i in 0..3) {
            mPaint[i] = Paint(Paint.ANTI_ALIAS_FLAG)
            mPaint[i]!!.style = Paint.Style.STROKE
            mPaint[i]!!.strokeCap = Paint.Cap.ROUND
            mPaint[i]!!.strokeJoin = Paint.Join.ROUND
            mPaint[i]!!.color = Color.parseColor("#f0cc36")
            mPaint[i]!!.strokeWidth = 9f
            mBeerPaint[i] = Paint(Paint.ANTI_ALIAS_FLAG)
            mBeerPaint[i]!!.style = Paint.Style.FILL
            mBeerPaint[i]!!.color = Color.parseColor("#fbce0f")
            mBubblePaint[i] = Paint(Paint.ANTI_ALIAS_FLAG)
            mBubblePaint[i]!!.style = Paint.Style.FILL
            mBubblePaint[i]!!.color = Color.parseColor("#f5fba1")
        }
        surfaceHolder = holder
        setZOrderOnTop(true)
        surfaceHolder!!.setFormat(PixelFormat.TRANSLUCENT)
        surfaceHolder!!.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(surfaceHolder: SurfaceHolder) {}
            override fun surfaceChanged(surfaceHolder: SurfaceHolder, i: Int, i1: Int, i2: Int) {}
            override fun surfaceDestroyed(surfaceHolder: SurfaceHolder) {
                if (mThread != null) {
                    mThread!!.interrupt()
                    mThread = null
                }
            }
        })
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mWidth = w.toFloat()
        mHeight = h.toFloat()
        mCenterX = (w / 2).toFloat()
        mCenterY = (h / 2).toFloat()
        mBaseLength = (w / 10).toFloat()
        mBgBaseLength = (w / 8).toFloat()
        for (i in 0..3) {
            mCurrentRippleX[i] = -2 * mBgBaseLength
        }
        mPath!!.reset()
        mPath!!.moveTo(0f, mCenterY + 2 * mBaseLength)
        mPath!!.lineTo(0f, mCenterY)
        mPath!!.lineTo(mBaseLength / 4, mCenterY - mBaseLength)
        mPath!!.lineTo(mBaseLength / 4, mCenterY - 1.5f * mBaseLength)
        mPath!!.lineTo(mBaseLength * 3 / 4, mCenterY - 1.5f * mBaseLength)
        mPath!!.lineTo(mBaseLength * 3 / 4, mCenterY - mBaseLength)
        mPath!!.lineTo(mBaseLength, mCenterY)
        mPath!!.lineTo(mBaseLength, mCenterY + 2 * mBaseLength)
        mPath!!.close()
    }

    private val animRunnable = Runnable {
        try {
            while (mCurrentState == STATE_SHOW) {
                Thread.sleep(5)
                flush()
                draw()
            }
            if (mCurrentState == STATE_HIDE) {
                clearCanvas()
            }
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    private fun flush() {
        if (mTemp >= 1) mTemp = 0f
        mTemp += DEFAULT_MOVE_SPEED
        for (i in 0..3) {
            var temp = mTemp - i * 0.25f
            if (temp < 0) temp += 1f
            mFraction[i] = temp
            if (mFraction[0] > i * 0.25f && !isItemReady[i]) {
                isItemReady[i] = true
            }
        }
    }

    private fun draw() {
        val canvas = surfaceHolder!!.lockCanvas() ?: return
        mPaint[0]!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) //使用这只画笔清屏，清屏后恢复画笔
        canvas.drawPaint(mPaint[0]!!)
        mPaint[0]!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
        for (i in 0..3) {
            drawItem(canvas, mFraction[i], i)
        }
        surfaceHolder!!.unlockCanvasAndPost(canvas)
    }

    private fun drawItem(canvas: Canvas, mFraction: Float, index: Int) {
        if (!isItemReady[index]) {
            return
        }
        canvas.save()
        canvas.translate(mFraction * mWidth, 0f)
        val mCurrentY: Float
        if (mFraction < 0.1) {  //嗷~ 从这开始画封口器以及确定波浪线高度
            mBeerPaint[index]!!.alpha = (255 * 10 * mFraction).toInt()
            mPaint[index]!!.alpha = (255 * 10 * mFraction).toInt()
            mBubblePaint[index]!!.alpha = (255 * 10 * mFraction).toInt()
            mCurrentY = mCenterY + 2.2f * mBaseLength
            canvas.drawLine(
                0.1f * mBaseLength,
                mCenterY - 2.5f * mBaseLength,
                0.9f * mBaseLength,
                mCenterY - 2.5f * mBaseLength,
                mPaint[index]!!
            )
        } else if (mFraction > 0.7) {
            mBeerPaint[index]!!.alpha = (255 / 0.3f * (1 - mFraction)).toInt()
            mPaint[index]!!.alpha = (255 / 0.3f * (1 - mFraction)).toInt()
            mBubblePaint[index]!!.alpha = (255 / 0.3f * (1 - mFraction)).toInt()
            mCurrentY = mCenterY - mBaseLength
            if (mFraction <= 0.75) {
                canvas.drawLine(
                    mBaseLength * 0.5f,
                    mCenterY - 2.5f * mBaseLength,
                    mBaseLength * 0.5f,
                    mCenterY - 2.5f * mBaseLength + mBaseLength / 0.05f * (mFraction - 0.7f),
                    mPaint[index]!!
                )
                canvas.drawLine(
                    0.1f * mBaseLength,
                    mCenterY - 2.5f * mBaseLength + mBaseLength / 0.05f * (mFraction - 0.7f),
                    0.9f * mBaseLength,
                    mCenterY - 2.5f * mBaseLength + mBaseLength / 0.05f * (mFraction - 0.7f),
                    mPaint[index]!!
                )
            } else {
                if (mFraction < 0.8) {
                    canvas.drawLine(
                        mBaseLength * 0.5f,
                        mCenterY - 2.5f * mBaseLength,
                        mBaseLength * 0.5f,
                        mCenterY - 1.5f * mBaseLength - mBaseLength / 0.05f * (mFraction - 0.75f),
                        mPaint[index]!!
                    )
                }
                canvas.drawLine(
                    mBaseLength / 4 - 6, mCenterY - 1.5f * mBaseLength - 6,
                    mBaseLength * 3 / 4 + 6, mCenterY - 1.5f * mBaseLength - 6, mPaint[index]!!
                )
            }
        } else {
            mCurrentY =
                mCenterY + 2.2f * mBaseLength - 3.2f * mBaseLength / 0.6f * (mFraction - 0.1f)
            canvas.drawLine(
                0.1f * mBaseLength,
                mCenterY - 2.5f * mBaseLength,
                0.9f * mBaseLength,
                mCenterY - 2.5f * mBaseLength,
                mPaint[index]!!
            )
        }
        canvas.drawPath(mPath!!, mPaint[index]!!) //嗷~ 在这画酒瓶
        mCurrentRippleX[index] += DEFAULT_RIPPLE_SPEED.toFloat()
        if (mCurrentRippleX[index] >= 0) {
            mCurrentRippleX[index] = -2 * mBgBaseLength
        }
        mBgPath!!.reset()
        mBgPath!!.moveTo(mCurrentRippleX[index], mCurrentY)
        for (i in 0..8) {
            mBgPath!!.rQuadTo(mBgBaseLength / 2, mBgBaseLength / 8, mBgBaseLength, 0f)
            mBgPath!!.rQuadTo(mBgBaseLength / 2, -mBgBaseLength / 8, mBgBaseLength, 0f)
        }
        mBgPath!!.lineTo(mWidth, mHeight)
        mBgPath!!.lineTo(0f, mHeight)
        mBgPath!!.close()
        canvas.clipPath(mPath!!)
        canvas.save()
        canvas.translate(-mBaseLength / 12, -mBaseLength / 10 - mBaseLength / 4 * (1 - mFraction))
        canvas.drawPath(mBgPath!!, mBubblePaint[index]!!) //嗷~ 在这画啤酒沫
        canvas.restore()
        canvas.drawPath(mBgPath!!, mBeerPaint[index]!!) //嗷~ 在这画啤酒
        canvas.restore()
    }

    fun show() {
        if (mCurrentState == STATE_SHOW) {
            return
        }
        mCurrentState = STATE_SHOW
        mThread = Thread(animRunnable)
        mThread!!.start()
    }

    fun hide() {
        if (mCurrentState == STATE_HIDE) {
            return
        }
        mCurrentState = STATE_HIDE
        resetData()
    }

    private fun clearCanvas() {
        val canvas = surfaceHolder!!.lockCanvas() ?: return
        mPaint[0]!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
        canvas.drawPaint(mPaint[0]!!)
        mPaint[0]!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
        surfaceHolder!!.unlockCanvasAndPost(canvas)
        mThread!!.interrupt()
        mThread = null
    }

    private fun resetData() {
        for (i in 0..3) {
            isItemReady[i] = false
            mCurrentRippleX[i] = -2 * mBgBaseLength
        }
        mTemp = 0f
    }

    companion object {
        private const val STATE_SHOW = 0
        private const val STATE_HIDE = 1
        private const val DEFAULT_RIPPLE_SPEED = 2
        private const val DEFAULT_MOVE_SPEED = 0.01f
    }
}